#ifndef __OS_NETIF_H
#define __OS_NETIF_H

#include <lib/list.h>
#include <sys/socket.h>
#include <lib/stddef.h>
#include <lib/stdint.h>
#include <lib/string.h>
#include <lib/type.h>
#include <os/memcache.h>

#define NETIF_DEFAULT_NAME "eth0"
#define NETIF_LOOP_NAME "loop"
#define LOOP_MTU 65536

#define NETIF_HWADDR_LEN 6U
#define NETIF_NAME_LEN 16

// net interface block
typedef struct
{
    list_t list;

    ip_addr_t ip_addr;
    ip_addr_t broad_addr;
    ip_addr_t netmask;
    ip_addr_t gateway;

    uint32_t mtu;                     // max transmission unit
    uint8_t hwaddr_len;               // hwaddr bytes number
    uint8_t hwaddr[NETIF_HWADDR_LEN]; // link level hardware address
    uint32_t flags;
    char name[NETIF_NAME_LEN];
    void *extension;
} net_interface_t;

extern fsal_t netif_fsal;

static inline net_interface_t *NetInterfaceCreate(void *extension)
{
    net_interface_t *netif = (net_interface_t *)KMemAlloc(sizeof(net_interface_t));
    if (netif)
    {
        memset(netif, 0, sizeof(net_interface_t));
        netif->extension = extension;
    }
    return netif;
}

#define NetInterfaceDestroy(netif) KMemFree(netif)

int NetIfIncRef(int sock);
int NetIfDecRef(int sock);
int NetIfRead(int sock, void *buff, size_t bytes);
int NetIfWrite(int sock, void *buff, size_t bytes);
int NetIfFcntl(int sock, int cmd, int arg);
int NetIfClose(int sock);
int NetIfSelect(int maxfds, fd_set_t readset, fd_set_t writeset, fd_set_t exceptset, timeval_t timeout);
int NetIfIoctl(int sock, int request, void *arg);

int NetworkInterfaceInit();
void NetworkInterfaceInput();
int NetInterfaceAdd(net_interface_t *netif);
int NetInterfaceDel(net_interface_t *netif);
net_interface_t *NetInterfaceFind(char *name);
net_interface_t *NetInterfaceFirst();
void NetInterfaceSetUp(net_interface_t *netif);
void NetInterfaceSetDown(net_interface_t *netif);
void NetInterfaceSetIpAddr(net_interface_t *netif, ip_addr_t addr);
void NetInterfaceSetBroadAddr(net_interface_t *netif, ip_addr_t addr);
void NetInterfaceSetNetMask(net_interface_t *netif, ip_addr_t addr);
void NetInterfaceSetMtu(net_interface_t *netif, int mtu);
void NetInterfaceSetFlags(net_interface_t *netif, int flags);
void NetInterfaceSetHwaddr(net_interface_t *netif, char *hwaddr);
void LwipInitTask();
void NetInterfaceDump();
void NetInterfacePoll();


#endif